import java.awt.Color;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.io.*;
import java.net.*;
import java.util.*;

public class MDServer 
{
	private List<Socket> clientList = new ArrayList<Socket>();
    private int num = 1;
    public LinkedList<ShapeObject> ShapeObjects = new LinkedList<ShapeObject>();
    private String fileName = "";
    
    public static void main (String [] args) 
    {
    	
    	int port = 8888;
    	if (args.length > 0) port = Integer.parseInt(args[0]);
    	
    	MDServer cs = new MDServer();
    	cs.listen(port);
    }

	synchronized void broadcastShapeObjects(){
		
		for (Socket s :  clientList) 
    	{
			ObjectOutputStream oos;
			try {
				oos = new ObjectOutputStream(s.getOutputStream());
				oos.writeObject(ShapeObjects);
			} catch (IOException e) {
				e.printStackTrace();
			}
    	}
	}
	synchronized void broadcastFile(File f){
		
		for (Socket s :  clientList) 
    	{
			ObjectOutputStream oos;
			try {
				oos = new ObjectOutputStream(s.getOutputStream());
				oos.writeObject(f);
			} catch (IOException e) {
				e.printStackTrace();
			}
    	}
	}
    void listen(int port) 
    {
    	try
    	{	
    	    ServerSocket listener = new ServerSocket(port);
        
    	    System.out.println(">>>> The MD Server <<<<");
    	    System.out.println("Telnet to " 
                               + InetAddress.getLocalHost().getHostName() 
    	    		       + " on port " + port);
    	    System.out.println("Use control-c to terminate MD Server.");
    	    
    	    while (true) 
    	    {
    	    	Socket client = listener.accept();
    	    	String userCredentials = "";
    	    	System.out.println("we are here");
    	    	Scanner remoteIn = new Scanner(client.getInputStream()); // *
    	    	while(remoteIn.hasNextLine())
    	    	{
    	    		userCredentials = remoteIn.nextLine();
    	    		System.out.println(userCredentials);
    	    		break;
    	    	}
    	    	// check if user is registered
    	    	PrintWriter out = new PrintWriter(client.getOutputStream(), true);
    	    	String name = checkUserCredentials(userCredentials);
    	    	if(!"invaliduser".equals(name))
    	    	{
    	    		System.out.println("Starting a client thread");
			    	out.println("true");
			    	System.out.println("Client thread started");
    	    		
			    	new MDHandler(client,this, name).start();
			    	System.out.println("New client number " + num + " from " 
			            		 + client.getInetAddress().getHostName()
						 + " on client's port " + client.getPort());
			    	add(client);
    	    	}
    	    	else
    	    		out.println("false");
    	    }
    	}
    	catch (IOException e)
    	{   System.out.println(e);   }
    }
    public String checkUserCredentials(String cred)
    {
    	int flag = 0;
    	System.out.println("Checking user credentials");
    	try
    	{
    		File f = new File("MDUserCreds");
    		FileReader fr = new FileReader(f);
    		BufferedReader br = new BufferedReader(fr);
    		String line = "";
    		while((line = br.readLine()) != null)
			{
    			if(line.equals(cred))
    			{
    				flag = 1;
    				System.out.println("User registered!");
    				break;
    			}
			}
			br.close();
    	}
    	catch(IOException e)
    	{
    		e.printStackTrace();
    	}
    	if(flag == 1)
    		return(cred.split(" ")[0]);
    	else
    	{
    		System.out.println("User NOT registered!");
    		return("invaliduser");
    	}
    }
    synchronized void add(Socket s) 
    {
    	clientList.add(s);  num++;
    }  
    
    synchronized void remove(Socket s) 
    {
    	clientList.remove(s);  num--;
    }  
	
    synchronized void broadcast(String message, String source) throws IOException 
    {
    	// Sends the message to every client including source.
    	for (Socket s :  clientList) 
    	{
    	    PrintWriter p = new PrintWriter(s.getOutputStream(), true);
    	    p.println(source + ": " + message + "\n");	
    	}
    	System.out.println(source+ ": " + message + "\n");
    }
    synchronized void refreshShapeObjects(LinkedList<ShapeObject> sobjs){
    	ShapeObjects.clear();
  	  	for(int i=0; i<sobjs.size(); i++){
  	  		ShapeObjects.add(sobjs.get(i));
  	    }
    }
    synchronized String getFileName(){
    	return this.fileName;
    }
    synchronized void setFileName(String fileName){
    	this.fileName = fileName;
    }
}
